package persist

import (
	"fetcher"
	"log"
	"os"
	"path"
	model "smarthome-model"
)

func ProdConfigSaver(baseDir string) chan interface{} {
	out := make(chan interface{})
	go func() {
		count := 0
		for {
			item := <-out
			count++
			log.Printf("Item Saver: got item #%d, %v", count, item)
			if prodParseItem, ok := item.(model.ProdParseItem); ok {
				if err := saveFile(prodParseItem, baseDir); err != nil {
					log.Printf("Item Saver: error saving item %v: %v\n", item, err)
					continue
				}
			}
		}
	}()
	return out
}

func saveFile(item model.ProdParseItem, baseDir string) error {
	filePath := path.Join(baseDir, item.FilePath)
	if item.IsDir {
		err := mkdirs(filePath)
		if err != nil {
			return err
		}
	} else {
		err := createFile(item, filePath)
		if err != nil {
			return err
		}
	}
	return nil
}

func createFile(item model.ProdParseItem, filePath string) error {
	dir := path.Dir(filePath)
	err := mkdirs(dir)
	if err != nil {
		log.Printf("[saveFile]: create file [%v] failed! e:%v\n", filePath, err)
		return err
	}
	file, err := os.Create(filePath)
	defer func(file *os.File) {
		err := file.Close()
		if err != nil {
			log.Printf("[saveFile]: close file [%v] failed! e:%v\n", filePath, err)
		}
	}(file)
	if err != nil {
		log.Printf("[saveFile]: create file [%v] failed! e:%v\n", filePath, err)
		return err
	}
	err = fetcher.DownloadFile(item.Url, file)
	if err != nil {
		log.Printf("[saveFile]: get file from [%v] to path [%v] failed! e:%v\n", item.Url, filePath, err)
		return err
	}
	return nil
}

func mkdirs(filePath string) error {
	// 判断文件是否存在,创建文件
	exists, err := pathExists(filePath)
	if err != nil {
		log.Printf("[saveFile]: get dir [%v] error! e: %v\n", filePath, err)
		return err
	}
	if exists {
		log.Printf("[saveFile]: dir [%v] exists\n", filePath)
	} else {
		log.Printf("[saveFile]: mkdir [%v]\n", filePath)
		err = os.MkdirAll(filePath, os.ModePerm)
		if err != nil {
			log.Printf("[saveFile]: mkdir [%v] failed!", filePath)
		} else {
			log.Printf("[saveFile]: mkdir [%v] success!", filePath)
		}
	}
	return nil
}

func pathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
